#pragma once
#include <cstdint>
#include <cstdio>

// 《深圳证券交易所组播行情数据分发协议V1.0》
// 本协议定义了深圳证券交易所组播行情数据分发系统的行情数据传输协议(MDPP)。
// MDDP 协议当前仅支持分发深交所二进制行情数据，
// MDDP 消息体内存储的应用消 息定义参见《深圳证券交易所 Binary 行情数据接口规范》

// 报文结构
// |-------------------|------------Protocol Body -------------|-------------------|
// +-------------------+-------------------+-------------------+-------------------+
// | Protocol Header   | Message Header    | Message Body     | Protocol Tail     |
// +-------------------+-------------------+-------------------+-------------------+
// ProtocolHeader->flag.msg_header == 1 时，报文体中包含 MessageHeader
// ProtocolHeader->flag.msg_header == 0 时，报文体中不包含 MessageHeader

// 消息头存在时，报文体结构
// |--------------------|--------------------|
// +--------------------+--------------------+
// | LEN1 | LEN2 | LEN3 | msg1 | msg2 | msg3 |
// +--------------------+--------------------+
// LEN1: uint32, msg1 的长度 = 4 * len1
// LEN2: uint32, msg2 的长度 = 4 * len2
// LEN3: uint32, msg3 的长度 = 4 * len3

// 消息头不存在时，报文体结构
// |--------------------|
// +--------------------+
// | msg1 | msg2 | msg3 |
// +--------------------+

// 报文尾： checksum： uint32

// 组播心跳报文
// ProtocolHeader->channel == 0时，为组播心跳报文，没有报文体，可以直接丢弃

// 数据流心跳报文
// ProtocolHeader->channel != 0 && ProtocolHeader->msg_count == 0时，为数据流心跳报文
// 没有报文体
// 数据流由 Channel 及 SenderId 唯一标识，当报文的 ResendBySeqNum 标志位为 1 时，
// 发送者会在数据流上周期性的数据流心跳报文，用于告知数据接收者当前数据流上
// 已发送的最后一笔数据消息对应的序号。
// 本协议将“数据流心跳报文”的 SeqNum
// 设置为当前数据流上已发送的最后一笔消 息的 SeqNum。
// 当数据流上没有发送过任何应用消息时，“数据流心跳报文”的 SeqNum 为 0。

// 数据流结束报文
// ProtocolHeader->channel != 0 && ProtocolHeader->msg_count == 0xffff时，为数据流结束报文
// 没有报文体

// 为了提升效率，MDDP 取消了《深圳证券交易所 Binary 行情数据接口规范》中
// 每条消息尾部的校验和，通过 MDDP 报文头的校验和对整个报文进行完整性校验。
// 接收者对 MDDP 报文进行完整性校验后，直接通过 MDDP 消息头完成消息切割并解码消息即可，
// 无需对每一条消息再进行单独的完整性校验

// seqnum 检测机制
// 数据流上每个组播报文的序号连续递增，由于组播会发生乱序、丢包和重包，
// 因此 数据接收者应该对数据流上的组播报文序号进行检查
// 1. SeqNum<下一个报文期望的报文序号 NextExpectedSeqNum，此时认为数据报文 为过期数据直接丢弃。
// 2. SeqNum=NextExpectedSeqNum，则处理报文，并设置下一个报文期望的报文序号
// NextExpectedSeqNum= SeqNum+MsgCount
// 3. SeqNum>NextExpectedSeqNum，说明可能发生了乱序或丢包，可采用两种处理 机制:
//      a) 直接判定为网络丢包，从当前数据包开始继续处理后续报文。
//          网络基础设施稳定，很少出现乱序时，可以考虑使用该机制。
//      b) 先判定网络发生乱序并缓存数据，当缓存的数据超过预设的缓冲区大小
//          或超时后依然未收到预期的报文，则判定为网络丢包。
//          使用缓存中序号最小的报文作为 NextExpectedSeqNum，继续处理缓存中以及后续的报文

// 定义协议头的结构体
struct MddpProtocolHeader
{
    std::uint8_t protocol;    // 协议标识，固定为 0xFF
    std::uint8_t version;     // 版本号，当前为 0x01
    std::uint8_t header_size; // 整个报文头的长度，指示报文头由几个 4 字节 words 组成
    std::uint8_t sender_id;   // 发送源标识
    std::uint16_t market_id;  // 市场标识
    std::uint16_t channel;    // 频道号，同一市场内的频道不重复，同一频道内的数据内容有序

    std::int64_t seq_num; // 报文序列号

    std::uint16_t msg_count; // 报文内消息条目数

    union
    {
        struct
        {
            std::uint8_t poss_dup_flag : 1;     // Bit 15: 可能重复标志
            std::uint8_t packet_type : 2;       // Bit 14-13: 报文类型标志
            std::uint8_t resend_by_seq_num : 1; // Bit 12: 是否支持按报文的 SeqNum 进行重传
            std::uint8_t compress : 2;          // Bit 11-10: 压缩标志
            std::uint8_t encryption : 2;        // Bit 9-8: 加密标志
            std::uint8_t msg_header : 1;        // Bit 7: 是否包含消息头
            std::uint8_t reserved : 7;          // Bit 6-0: 预留
        };
        uint16_t all;
    } flag;

    std::uint32_t original_size; // 原始数据大小（可选）

    std::uint32_t compressed_size; // 压缩后数据大小（可选）
    std::uint32_t encrypted_size;  // 加密后数据大小（可选）
    // std::uint8_t padding[4];        // 字节对齐填充位（可选），确保报文头长度为 4 字节整数倍，无意义

    // void ntoh()
    // {
    //     market_id = __builtin_bswap16(market_id);
    //     channel = __builtin_bswap16(channel);
    //     seq_num = __builtin_bswap64(seq_num);
    //     msg_count = __builtin_bswap16(msg_count);
    //     flag.all = __builtin_bswap16(flag.all);

    //     if (headerLength() > 20)
    //         original_size = __builtin_bswap32(original_size);
    //     if (headerLength() > 24)
    //         compressed_size = __builtin_bswap32(compressed_size);
    //     if (headerLength() > 28)
    //         encrypted_size = __builtin_bswap32(encrypted_size);
    // }

    int headerLength() const
    {
        return header_size * 4;
    }

    void print()
    {
        printf("{\n");
        printf("\theader_size: %d,\n", header_size);
        printf("\tsender_id: %d,\n", sender_id);
        printf("\tmarket_id: %d,\n", market_id);
        printf("\tchannel: %d,\n", channel);
        printf("\tseq_num: %ld,\n", seq_num);
        printf("\tmsg_count: %d,\n", msg_count);
        printf("\tposs_dup_flag: %d,\n", flag.poss_dup_flag);
        printf("\tpacket_type: %d,\n", flag.packet_type);
        printf("\tresend_by_seq_num: %d,\n", flag.resend_by_seq_num);
        printf("\tcompress: %d,\n", flag.compress);
        printf("\tencryption: %d,\n", flag.encryption);
        printf("\tmsg_header: %d,\n", flag.msg_header);
        printf("\treserved: %d,\n", flag.reserved);

        // 根据header_size判断是否有可选字段
        if (headerLength() > 20)
            printf("\toriginal_size: %d,\n", original_size);
        if (headerLength() > 24)
            printf("\tcompressed_size: %d,\n", compressed_size);
        if (headerLength() > 28)
            printf("\tencrypted_size: %d,\n", encrypted_size);

        if (isHeartbeat())
            printf("\tisHeartbeat: true,\n");
        else if (isDataHeartbeat())
            printf("\tisDataHeartbeat: true,\n");
        else if (isDataEnd())
            printf("\tisDataEnd: true,\n");
        else if (isData())
            printf("\tisData: true,\n");
        else
            printf("\tUnknown Type,\n");

        printf("}\n");
    }

    bool isHeartbeat() const
    {
        return channel == 0;
    }
    bool isDataHeartbeat() const
    {
        return channel != 0 && msg_count == 0;
    }
    bool isDataEnd() const
    {
        return channel != 0 && msg_count == 0xffff;
    }
    bool isData() const
    {
        return channel != 0 && msg_count != 0 && msg_count != 0xffff;
    }

    static uint32_t adler32(const uint8_t *data, size_t len)
    {
        uint32_t a = 1, b = 0;
        for (size_t i = 0; i < len; ++i)
        {
            a = (a + data[i]) % 65521;
            b = (b + a) % 65521;
        }
        return (b << 16) | a;
    }
};

// 《深圳证券交易所 Binary 行情数据接口规范》
// 本规范定义了深圳证券交易所二进制行情数据接口的消息格式。
// 行情网关 MDGW 现场版没有数据重传功能，网络版有数据重传功能
// 用户行情系统：VSS
// 行情网关为用户行情系统提供两个服务端口，实时数据端口（默认为 9129），
// 重传 服务端口(默认为 9130)。每一个端口只能建立一个 TCP/IP 连接。
// 只有网络版行情网关 提供重传服务端口。
// 行情网关和用户行情系统必须位于同一个安全网络之中，
// 行情网关和用户行情系统 之间传输的数据是非加密的，数据传输安全由接入用户网络保证

// 本接口规范中的所有整数类型字段都采用高字节序（BIG-ENDIAN）编码方式。

namespace MddpMessage
{
    ////////////////////////数据类型定义/////////////////
    // Nx(y)表示相应的类型实际为浮点数类型，
    // 其中 x 表示整数与小数总计位数，不包括 小数点，y 表示小数位数，
    // 比如对于 Price 类型，Int64 值 186400 表示的价格为 18.6400。
    // 字符串 统一使用 UTF-8 编码
    struct CompID
    {
        char val[20];
    };

    template <typename T>
    class BigEndian
    {
        T value;

    public:
        constexpr T val() const
        {
            if constexpr (sizeof(T) == 1)
                return value;
            else if constexpr (sizeof(T) == 2)
                return __builtin_bswap16(value);
            else if constexpr (sizeof(T) == 4)
                return __builtin_bswap32(value);
            else if constexpr (sizeof(T) == 8)
                return __builtin_bswap64(value);
            else
                static_assert(sizeof(T) != sizeof(T), "Unsupported size for T");
        }
    };

    typedef BigEndian<uint8_t> UInt8;
    typedef BigEndian<uint16_t> UInt16;
    typedef BigEndian<uint32_t> UInt32;
    typedef BigEndian<uint64_t> UInt64;
    typedef BigEndian<int8_t> Int8;
    typedef BigEndian<int16_t> Int16;
    typedef BigEndian<int32_t> Int32;
    typedef BigEndian<int64_t> Int64;

    typedef Int64 Price; // N13(4)
    typedef Int64 Qty;   // N15(2)
    typedef Int64 Amt;   // N18(4)
    typedef Int64 SeqNum;
    typedef UInt16 Boolean;
    typedef UInt32 Length;
    typedef Int64 LocalTimeStamp; // 本地时间戳YYYYMMDDHHMMSSsss
    typedef UInt32 NumInGroup;
    typedef UInt32 LocalMktDate; // 本地市场日期，格式 YYYYMMDD
    struct SecurityID            // 证券代码
    {
        char m_val[8];
        int val() const
        {
            int ret = 0;
            for (int i = 0; i < 8; ++i)
            {
                if (m_val[i] >= '0' && m_val[i] <= '9')
                    ret = ret * 10 + m_val[i] - '0';
            }
            return ret;
        }
    };

    ////////////////////////会话层域定义//////////////////////////
    typedef UInt32 BodyLength;
    typedef UInt32 MsgType;
    typedef CompID SenderCompID;
    typedef CompID TargetCompID;

    struct Password
    {
        char val[16];
    };

    struct Text
    {
        char val[200]; // 可能包含中文字符
    };

    typedef Int32 HeartBtInt;
    struct DefaultApplVerID
    {
        char val[32]; // 通信版本号，保存为字符串，如 1.01
    };

    typedef Int32 SessionStatus;

    //////////////////////业务层域定义////////////////////////////
    typedef char AmountStatus;           // 1 额度不可用，2 额度可用
    typedef SeqNum ApplBegSeqNum;        // 应用消息起始序号
    typedef SeqNum ApplEndSeqNum;        // 应用消息结束序号
    typedef SeqNum ApplLastSeqNum;       // 最后一条行情消息的记录号
    typedef SeqNum ApplSeqNum;           // 消息记录号，从1开始计数
    typedef Qty AuctionVolumeTrade;      // 匹配成交成交量
    typedef Amt AuctionValueTrade;       // 匹配成交成交金额
    typedef SeqNum BidApplSeqNum;        // 买方委托索引
    typedef UInt16 BidExecInstType;      // 竞买成交方式 1=单一主体中标 2=多主体单一价格中标 3=多主体多重价格中标
    typedef UInt16 BidTransType;         // 竞买业务类别 1=竞买预约申报 2=竞买发起申报 3=竞买应价申报
    typedef UInt16 BusinessRejectReason; // 拒绝原因
    struct BusinessRejectRefID
    {
        char val[10]; // 被拒绝消息对应的业务层 ID
    };
    struct BusinessRejectText
    {
        char val[50]; // 拒绝原因说明，最多50个字节
    };
    typedef UInt16 ChannelNo;                     // 频道代码
    typedef LocalTimeStamp ComplexEventStartTime; // 冷静期开始时间
    typedef LocalTimeStamp ComplexEventEndTime;   // 冷静期结束时间
    struct ConfirmID
    {
        char val[8]; // 定价行情约定号
    };
    struct ContactInfo
    {
        char val[30]; // 联系方式，最多30个字节
    };
    struct Contactor
    {
        char val[12]; // 联系人，最多12个字节
    };
    typedef Boolean EndOfChannel;    // 频道结束标志
    typedef char ExecType;           // 执行类型 4=Cancelled，表示已撤销 F=Trade，表示已成交
    typedef UInt16 ExpirationDays;   // 期限，单位为天数
    typedef uint8_t ExpirationType;  // 期限类型
    typedef char FinancialStatus[8]; // 证券状态，每个字节表示一种状态，最多可同时表示八种状态
    typedef char Headline[128];      // 公告标题，最多128个字节，可能包含中文字符
    typedef Price HighLimitPrice;    // 价格上限，0表示无价格上限
    typedef char InvestorType[2];    // 交易主体类型 01=自营 02=资管 03=机构经纪 04=个人经纪
    typedef char InvestorID[10];     // 交易主体代码
    typedef char InvestorName[120];  // 客户名称，最多120个字节，可能包含中文字符
    typedef Price LastPx;            // 成交价格
    typedef Qty LastQty;             // 成交数量
    typedef Price LowLimitPrice;     // 价格下限
    typedef Price MarginPrice;       // 达成成交的边际价格，在竞买成交方式为多主体单一价格中标或多主体多重价格中标时使用
    typedef char MarketID[8];        // 市场代码，例如XHKG表示港股通
    typedef char MarketSegmentID[8]; // 市场板块代码
    typedef Int64 MDEntryPx;         // 行情条目价格，N18（6）

    typedef Qty MDEntrySize;                   // 行情条目数量
    typedef char MDEntryType[2];               // 行情条目类别
    typedef UInt16 MDPriceLevel;               // 买卖盘档位
    typedef char MDStreamID[3];                // 行情类别
    typedef Qty MinQty;                        // 最低成交数量
    typedef char MemberID[6];                  // 交易商代码
    typedef char Memo[160];                    // 备注，最多160个字节，可能包含中文字符
    typedef char NewsID[8];                    // 公告索引/增值信息索引
    typedef NumInGroup NoComplexEventTimes;    // VCM冷静期个数
    typedef NumInGroup NoMDEntries;            // 行情条目个数
    typedef NumInGroup NoMDStreamID;           // 行情类别个数
    typedef NumInGroup NoOrders;               // 价位揭示委托笔数
    typedef NumInGroup NoSubTradingPhaseCodes; // 细分交易阶段个数
    typedef NumInGroup NoSwitch;               // 开关个数
    typedef Int64 NumberOfOrders;              // 价位总委托笔数
    typedef Int64 NumTrades;                   // 成交笔数
    typedef SeqNum OfferApplSeqNum;            // 卖方委托索引
    typedef Qty OrderQty;                      // 订单数量
    typedef char OrdType;                      // 订单类型，1表示市价，2表示限价，U表示本方最优
    typedef LocalTimeStamp OrigTime;           // 数据生成时间，采用本地时间戳表示
    typedef Amt PosAmt;                        // 日中剩余额度
    typedef Price PrevClosePx;                 // 昨收价
    typedef char QuoteID[10];                  // 报价消息编号
    // typedef char RawData[n];                 // 变长二进制数据
    typedef char RawDataFormat[8]; // 二进制数据格式，取值为TXT、PDF、DOC

    typedef Length RawDataLength;         // 二进制数据长度
    typedef UInt32 RefMsgType;            // 被拒绝的消息类型
    typedef SeqNum RefSeqNum;             // 引用的消息序号
    typedef char RejectText[16];          // 拒绝原因说明，最多16个字节，可能包含中文字符
    typedef uint8_t ResendStatus;         // 重传状态
    typedef uint8_t ResendType;           // 重发种类
    typedef char SecondaryOrderID[16];    // 竞买场次编号
    typedef SecurityID SecurityID;        // 证券代码
    typedef char SecurityIDSource[4];     // 证券代码源，102表示深圳证券交易所，103表示香港交易所
    typedef Boolean SecuritySwitchStatus; // 开关状态
    typedef UInt16 SecuritySwitchType;    // 开关类别
    typedef uint8_t SettlPeriod;          // 结算周期
    typedef UInt16 SettlType;             // 结算方式，103表示多边净额，104表示逐笔全额
    typedef char Side;                    // 买卖方向，1表示买，2表示卖，G表示借入，F表示出借
    typedef UInt32 StockNum;              // 证券只数
    typedef char SubTradingPhaseCode[8];  // 交易方式所处的交易阶段代码
    typedef UInt16 TemplateID;            // 模板号
    typedef Amt ThresholdAmount;          // 每日初始额度
    typedef Amt TotalValueTrade;          // 成交总金额
    typedef Qty TotalVolumeTrade;         // 成交总量
    typedef LocalMktDate TradeDate;       // 交易日期
    typedef char TraderCode[8];           // 交易员代码
    typedef char TradingPhaseCode[8];     // 产品所处的交易阶段代码
    typedef char TradingSessionID[4];     // 交易会话ID 1=日间，Day

    typedef char TradingSessionSubID[4];     // 交易会话子ID
    typedef uint8_t TradingType;             // 交易方式，1表示匹配成交，2表示协商成交，3表示点击成交，4表示询价成交，5表示竞买成交
    typedef LocalTimeStamp TradSesEndTime;   // 交易会话结束时间
    typedef LocalTimeStamp TradSesStartTime; // 交易会话开始时间
    typedef UInt16 TradSesStatus;            // 交易会话状态
    typedef LocalTimeStamp TransactTime;     // 委托时间
    typedef UInt16 UserNum;                  // 用户数目
    typedef char VersionCode[16];            // 版本代码

    namespace MessageType
    {
        enum MessageType
        {
            LogOn = 1,
            Logout = 2,
            Heartbeat = 3,
            ChannelHeartbeat = 390095,
            ResendRequest = 390094,
            UserInfoReportInfo = 390093,
            SnapshotMarketChannelStatics = 390090,
            BusinessRejectInfo = 8,
            TradingSessionInfo = 390019,
            SecurityInfo = 390013,
            NewsInfo = 390012,
            MarketData = 300111, // 3xxx11

            TickByTickOrderFlow = 300192, // 30xx92
            TickByTickTrade = 300191,     // 30xx91
        };
    } // namespace MessageType

#pragma pack(1)

    struct Header
    {
        UInt32 msg_type; // 消息类型
        UInt32 msg_len;  // 消息长度,只是body的长度，不包含头部和尾部
    };

    namespace Manage
    {
        struct LogOn
        {
            // MsgType = 1
            SenderCompID sender_comp_id;          // 发送方标识
            TargetCompID target_comp_id;          // 接收方标识
            HeartBtInt heart_bt_int;              // 心跳间隔
            Password password;                    // 密码
            DefaultApplVerID default_appl_ver_id; // 通信版本号
        };

        struct Logout
        {
            // MsgType = 2
            SessionStatus session_status; // 会话状态
            // 退出时的会话状态。
            // 0=会话活跃
            // 1=会话口令已更改
            // 2=将过期的会话口令
            // 3=新会话口令不符合规范
            // 4=会话退登完成
            // 5=不合法的用户名或口令
            // 6=账户锁定
            // 7=当前时间不允许登录
            // 8=口令过期
            // 9=收到的MsgSeqNum(34)太小
            // 10=收到的NextExpectedMsgSeqNum(789)太大。
            // 101=其他
            // 102=无效消息
            Text text; // 文本, 注销原因
        };
    } // namespace Manage

    namespace Common
    {
        struct Heartbeat
        {
            // MsgType = 3, BodyLength=0
        };

        struct ChannelHeartbeat
        {
            // 频道心跳发送间隔为 3 秒。
            // MsgType = 390095
            ChannelNo channel_no;             // 频道号
            ApplLastSeqNum appl_last_seq_num; // 应用消息最后序号
            EndOfChannel end_of_channel;      // 频道结束标志
        };

        struct ResendRequest
        {
            // MsgType = 390094
            ResendType resend_type;         // 重发种类
            ChannelNo channel_no;           // 频道号
            ApplBegSeqNum appl_beg_seq_num; // 应用消息起始序号
            ApplEndSeqNum appl_end_seq_num; // 应用消息结束序号
            NewsID news_id;                 // 公告索引/增值信息索引
            ResendStatus resend_status;     // 重传状态
            RejectText reject_text;         // 拒绝原因说明
        };

        struct UserInfoReportInfo
        {
            // msgtype = 390093
            OrigTime orig_time;       // 数据生成时间
            VersionCode version_code; // 版本代码
            UserNum user_num;         // 用户数目
        };

        struct SnapshotMarketChannelStatics
        {
            // msgtype = 390090
            OrigTime orig_time;           // 数据生成时间
            ChannelNo channel_no;         // 频道号
            NoMDStreamID no_md_stream_id; // 行情类别个数
            // 每个行情类别定义
            struct Market
            {
                MDStreamID md_stream_id;             // 行情类别
                StockNum stock_num;                  // 证券只数
                TradingPhaseCode trading_phase_code; // 闭市状态 第 0 位： T=连续竞价（全部证券尚未闭市） E=已闭市（全部证券已闭市）
            };
        };

        // MsgType = 8
        struct BusinessRejectInfo
        {
            RefSeqNum ref_seq_num;                       // 被拒绝消息的消息序号
            RefMsgType ref_msg_type;                     // 被拒绝的消息类型
            BusinessRejectRefID business_reject_ref_id;  // 被拒绝消息对应的业务层 ID
            BusinessRejectReason business_reject_reason; // 拒绝原因
            BusinessRejectText business_reject_text;     // 拒绝原因说明
        };

    } // namespace Common

    namespace RealTime // 实时消息
    {
        // 390019
        struct TradingSessionInfo
        {
            OrigTime orig_time;                         // 数据生成时间
            ChannelNo channel_no;                       // 频道代码
            MarketID market_id;                         // 市场代码
            MarketSegmentID market_segment_id;          // 市场板块代码，预留
            TradingSessionID trading_session_id;        // 交易会话 ID
            TradingSessionSubID trading_session_sub_id; // 交易会话子 ID
            TradSesStatus trad_ses_status;              // 交易会话状态，预留
            TradSesStartTime trad_ses_start_time;       // 交易会话起始时间，预留
            TradSesEndTime trad_ses_end_time;           // 交易会话结束时间，预留
            ThresholdAmount threshold_amount;           // 每日初始额度
            PosAmt pos_amt;                             // 日中剩余额度，额度不可用时，发布固定值 0.0000
            AmountStatus amount_status;                 // 额度状态
        };
        struct SecurityInfo
        {
            // 390013
            OrigTime orig_time;                  // 数据生成时间
            ChannelNo channel_no;                // 频道代码
            SecurityID security_id;              // 证券代码
            SecurityIDSource security_id_source; // 证券代码源
            FinancialStatus financial_status;    // 证券状态
            NoSwitch no_switch;                  // 开关个数
            // 每个开关定义
            struct Switch
            {
                SecuritySwitchType security_switch_type;     // 开关类别
                SecuritySwitchStatus security_switch_status; // 开关状态
            };
        };

        struct NewsInfo
        {
            // 390012
            OrigTime orig_time;            // 公告时间
            ChannelNo channel_no;          // 频道代码
            NewsID news_id;                // 唯一标识，空串表示公告概要，公告概要会重复发送，可通过公告概要确定公告是否有遗漏或是修改
            Headline headline;             // 公告标题
            RawDataFormat raw_data_format; // 二进制数据格式
            RawDataLength raw_data_length; // 二进制数据长度
            // char* raw_data;              // 二进制数据
        };

        struct MarketData // 快照行情
        {
            // 3xxx11
            OrigTime orig_time;                  // 数据生成时间
            ChannelNo channel_no;                // 频道代码
            MDStreamID md_stream_id;             // 行情类别
            SecurityID security_id;              // 证券代码
            SecurityIDSource security_id_source; // 证券代码源
            TradingPhaseCode trading_phase_code; // 产品所处的交易阶段代码
            PrevClosePx prev_close_px;           // 昨收价
            NumTrades num_trades;                // 成交笔数
            TotalVolumeTrade total_volume_trade; // 成交总量
            TotalValueTrade total_value_trade;   // 成交总金额
            // ExtendFields extend_fields;          // 各业务扩展字段
            enum Type
            {
                TypeOpeningCallAuctionMarketData = 300111,        // 集中竞价交易业务行情
                TypeAfterHoursBlockTradingMarketData = 300611,    // 盘后定价交易业务行情
                TypeIndexMarketData = 309011,                     // 指数行情
                TypeVolumeStatisticsIndicatorMarketMata = 309111, // 成交量统计指标行情
                TypeRealTimeHongKongStockMarketData = 306311,     // 港股实时行情
                TypeAfterHoursPricingTradingMarketData = 303711,  // 盘后定价交易业务行情
                TypeRealTimeBondSpotTradingMarketData = 300211,   // 债券现券交易业务行情
            };
            uint8_t *getExtendFileds() const
            {
                return ((uint8_t *)&total_value_trade) + sizeof(TotalValueTrade);
            }
            struct OpeningCallAuctionMarketData
            {
                NoMDEntries no_md_entries; // 行情条目个数
                struct MDEntry
                {
                    MDEntryType md_entry_type;       // 行情条目类别
                    MDEntryPx md_entry_px;           // 行情条目价格
                    MDEntrySize md_entry_size;       // 行情条目数量
                    MDPriceLevel md_price_level;     // 买卖盘档位
                    NumberOfOrders number_of_orders; // 价位总委托笔数, 为 0 表示不揭示
                    NoOrders no_orders;              // 价位揭示委托笔数, 为 0 表示不揭示
                    struct Order
                    {
                        OrderQty order_qty; // 委托数量
                    };
                    int getSelfSize() const
                    {
                        return sizeof(MDEntry) + sizeof(Order) * no_orders.val();
                    }
                };
                uint8_t *getExtendFileds() const
                {
                    return ((uint8_t *)&no_md_entries) + sizeof(NoMDEntries);
                }
            };
            struct AfterHoursBlockTradingMarketData
            {
                NoMDEntries no_md_entries; // 行情条目个数
                struct MDEntry
                {
                    MDEntryType md_entry_type; // 行情条目类别 0=买入 1=卖出
                    MDEntryPx md_entry_px;     // 价格
                    MDEntrySize md_entry_size; // 数量
                };
            };
            struct IndexMarketData
            {
                NoMDEntries no_md_entries; // 行情条目个数
                struct MDEntry
                {
                    MDEntryType md_entry_type; // 行情条目类别 3=当前指数 xa=昨日收盘指数 xb=开盘指数 xc=最高指数 xd=最低指数 xl=收盘指数 xm=收盘指数 2（预留） xn=收盘指数 3（预留）
                    MDEntryPx md_entry_px;     // 指数点位
                };
            };
            struct VolumeStatisticsIndicatorMarketMata
            {
                StockNum stock_num; // 统计量指标样本个数
            };

            struct RealTimeHongKongStockMarketData
            {
                NoMDEntries no_md_entries; // 行情条目个数
                struct MDEntry
                {
                    MDEntryType entry_type;   // 行情条目类别，0=买入，1=卖出，2=最近价，7=最高价，8=最低价，xe=涨停价，xf=跌停价，xh=按盘价（收盘后为收盘价），xi=参考价，xr=买盘上限价，xs=买盘下限价，xt=卖盘上限价，xu=卖盘下限价
                    MDEntryPx entry_price;    // 价格
                    MDEntrySize entry_size;   // 数量
                    MDPriceLevel price_level; // 买卖盘档位
                };
                NoComplexEventTimes no_complex_event_times; // VCM冷静期个数
                struct ComplexEventTimes
                {
                    ComplexEventStartTime complex_event_start_time; // 冷静期开始时间
                    ComplexEventEndTime complex_event_end_time;     // 冷静期结束时间
                };
            };

            struct AfterHoursPricingTradingMarketData
            {
                NoMDEntries no_md_entries; // 行情条目个数
                struct MDEntry
                {
                    MDEntryType md_entry_type; // 行情条目类别 0=买入 1=卖出
                    MDEntryPx md_entry_px;     // 价格
                    MDEntrySize md_entry_size; // 数量
                };
            };

            struct RealTimeBondSpotTradingMarketData
            {
                NoMDEntries no_md_entries; // 行情条目个数
                struct MDEntry
                {
                    MDEntryType md_entry_type;       // 行情条目类别0=买入 1=卖出 2=最近价 4=开盘价 5=收盘价 7=最高价 8=最低价 9=加权平均价 x1=升跌一 x2=升跌二 x3=买入汇总（总量及加权平均 价） x4=卖出汇总（总量及加权平均 价） xj=加权平均价涨跌 BP xk=昨收盘加权平均价 xv=匹配成交最近价
                    MDEntryPx md_entry_px;           // 价格
                    MDEntrySize md_entry_size;       // 数量
                    MDPriceLevel md_price_level;     // 买卖盘档位
                    NumberOfOrders number_of_orders; // 价位总委托笔数, 为 0 表示不揭示
                    NoOrders no_orders;              // 价位揭示委托笔数, 为 0 表示不揭示
                    struct Order
                    {
                        OrderQty order_qty; // 委托数量
                    };
                };
                NoSubTradingPhaseCodes no_sub_trading_phase_codes; // 细分交易阶段个数
                struct SubTradingPhaseCodeEntry
                {
                    SubTradingPhaseCode sub_trading_phase_code; // 交易方式所处的交易阶段代码
                    TradingType trading_type;                   // 交易方式 1=匹配成交 2=协商成交 3=点击成交 4=询价成交 5=竞买成交
                };
                AuctionVolumeTrade auction_volume_trade; // 匹配成交成交量
                AuctionValueTrade auction_value_trade;   // 匹配成交成交金额
            };
        };

        struct TickByTickOrderFlow
        {
            // 30xx92
            ChannelNo channel_no;                // 频道代码
            ApplSeqNum appl_seq_num;             // 消息记录号，从1开始计数
            MDStreamID md_stream_id;             // 行情类别
            SecurityID security_id;              // 证券代码
            SecurityIDSource security_id_source; // 证券代码源
            Price price;                         // 委托价格
            OrderQty order_qty;                  // 委托数量
            Side side;                           // 买卖方向，1=买，2=卖，G=借入，F=出借
            TransactTime transact_time;          // 委托时间
            // ExtendFields extend_fields;          // 各业务扩展字段
        };

        struct TickByTickTranscation
        {
            // 30xx91
            ChannelNo channel_no;                // 频道代码
            ApplSeqNum appl_seq_num;             // 消息记录号，从1开始计数
            MDStreamID md_stream_id;             // 行情类别
            BidApplSeqNum bid_appl_seq_num;      // 买方委托索引，从1开始计数，0表示无对应委托
            OfferApplSeqNum offer_appl_seq_num;  // 卖方委托索引，从1开始计数，0表示无对应委托
            SecurityID security_id;              // 证券代码
            SecurityIDSource security_id_source; // 证券代码源
            LastPx last_px;                      // 成交价格
            LastQty last_qty;                    // 成交数量
            ExecType exec_type;                  // 成交类别，4=撤销 F=成交
            TransactTime transact_time;          // 成交时间
            // ExtendFields extend_fields;          // 各业务扩展字段
        };

    } // namespace RealTime

    struct Tail
    {
        UInt32 checksum; // 校验和
    };

#pragma pack()

    template <class T>
    struct Body
    {
        T val;
    };

}; // namespace MddpMessage
